package com.fingard.dsp.bank.directbank.baofoo01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 宝付批量代收付
 * -- 当前支持银谷接入
 */
public class BaoFoo01BatPayRec extends BaoFoo01Base implements IBatPayRec {
    /**
     * 宝付批量代付
     */
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);

        FileOutputStream fos = null;
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req1988.ownAct, "");
            if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath) || !FileHelper.existFile(actItem.oppCertFilePath)) {
                retAts.respCode = "0";
                if (actItem == null) {
                    retAts.respInfo = "未找到账号" + p_req1988.ownAct + "的批量商户配置节点";
                } else {
                    retAts.respInfo = "账号" + p_req1988.ownAct + "的证书文件不存在";
                }
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }

            Map<String, String> postParams = new HashMap<String, String>();

            postParams.put("member_id", actItem.merchantId);
            postParams.put("terminal_id", actItem.termId);
            postParams.put("data_type", "xml");

            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\" ?>");
            xmlWriter.writeStartElement("trans_content");
            xmlWriter.writeStartElement("trans_reqDatas");

            while (p_req1988.readRecord()) {
                xmlWriter.writeStartElement("trans_reqData");
                xmlWriter.writeElementString("trans_no", p_req1988.readedDetail.askNumber);
                xmlWriter.writeElementString("trans_money", p_req1988.readedDetail.payAmount);
                xmlWriter.writeElementString("to_acc_name", p_req1988.readedDetail.recName);
                xmlWriter.writeElementString("to_acc_no", p_req1988.readedDetail.recAct);
                xmlWriter.writeElementString("to_bank_name", p_req1988.readedDetail.recBankName);
                xmlWriter.writeElementString("to_pro_name", p_req1988.readedDetail.getOppProvinceAndCity2()[0]);
                xmlWriter.writeElementString("to_city_name", p_req1988.readedDetail.getOppProvinceAndCity2()[1]);
                xmlWriter.writeElementString("to_acc_dept", p_req1988.readedDetail.recBankLocation);
                xmlWriter.writeElementString("trans_card_id", p_req1988.readedDetail.certNum);
                xmlWriter.writeElementString("trans_mobile", p_req1988.readedDetail.cellPhone);
                xmlWriter.writeElementString("trans_summary", "");
                xmlWriter.writeEndElement();
            }

            xmlWriter.writeEndDocument();

            String base64Str = Base64Encode(xmlWriter.toXmlString());
            String data_content = encryptByPriPfxFile(base64Str, actItem.ownKeyStorePath, actItem.ownKeyPassword);

            postParams.put("data_content", data_content);
            postParams.put("version", "4.0.0");

            // 请求报文
            WriteBankLogLn("加密数据: " + xmlWriter.toXmlString());

            File batFile = new File("D:\\withdraw" + File.separator + p_req1988.reqBatchNO + ".txt");
            if (!batFile.getParentFile().exists()) {
                batFile.getParentFile().mkdirs();
            }

            if (!batFile.exists()) {
                batFile.createNewFile();
            }

            fos = new FileOutputStream(batFile);
            fos.write(xmlWriter.toXmlString().getBytes());

            String[] tmpStrRet = sendToBank("withdraw", postParams, actItem);

            // 解析银行返回
            if (tmpStrRet[0].length() == 0) {
                if (tmpStrRet[1].contains("trans_content")) {
                    //明文返回,报文错误处理
                    retAts.respCode = "-1";
                    retAts.respInfo = "报文参数设置错误";
                } else {
                    //密文返回
                    //第一步：公钥解密
                    String decryptStr = decryptByPubCerFile(tmpStrRet[1], actItem.oppCertFilePath);
                    //第二步BASE64解密
                    String respXml = Base64Decode(decryptStr);

                    WriteBankLogStep3(respXml);

                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(respXml, tmpSbMsg);

                    if (tmpBkReader != null) {
                        String tmpRespCode = tmpBkReader.getFirstText("/trans_content/trans_head/return_code");

                        if (tmpRespCode.equals("0000")) {
                            retAts.respCode = "0";
                            retAts.respInfo = tmpBkReader.getFirstText("/trans_content/trans_head/return_msg");
                            retAts.reqSeqID = p_req1988.reqBatchNO;
                            retAts.transState = tmpRespCode;
                            retAts.payInfoCode = retAts.transState;
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = tmpBkReader.getFirstText("/trans_content/trans_head/return_msg");
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpSbMsg.toString();
                    }
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                retAts.respCode = "0";
                retAts.respInfo = tmpStrRet[1];
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = tmpStrRet[0];
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            e.printStackTrace();
        } finally {
            if (fos != null) {
                fos.close();
            }
        }

        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1988.reqBatchNO;
        }

        retAts.writeRetToATS();
        return retAts;
    }

    /**
     * 宝付批量代付状态查询
     */
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        retAts.respCode = "";

        FileInputStream fis = null;
        BufferedReader bufferedReader = null;
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req1998.ownAct, "");
            if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath) || !FileHelper.existFile(actItem.oppCertFilePath)) {
                if (actItem == null) {
                    throw new Exception("未找到账号" + p_req1998.ownAct + "对应的商户配置节点");
                } else {
                    throw new Exception("账号" + p_req1998.ownAct + "对应的证书文件不存在");
                }
            }

            Map<String, String> postParams = new HashMap<String, String>();

            postParams.put("member_id", actItem.merchantId);
            postParams.put("terminal_id", actItem.termId);
            postParams.put("data_type", "xml");
//	        postParams.put("data_content", "");
//	        postParams.put("version", "4.0.0");

            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\" ?>");
            xmlWriter.writeStartElement("trans_content");
            xmlWriter.writeStartElement("trans_reqDatas");

            String batDetail = "";
            String line = null;
            fis = new FileInputStream("D:\\withdraw" + File.separator + p_req1998.reqBatchNO + ".txt");
            bufferedReader = new BufferedReader(new InputStreamReader(fis));

            while ((line = bufferedReader.readLine()) != null) {
                batDetail += line;
            }
            StringBuilder SbMsg = new StringBuilder();
            XmlTextReader BkReader = loadBankRespXmlReader(batDetail, SbMsg);

            if (BkReader != null) {
                while (BkReader.read("/trans_content/trans_reqDatas/trans_reqData")) {
                    String trans_no = BkReader.readedXElement.getSingleText("trans_no");
                    xmlWriter.writeStartElement("trans_reqData");
                    xmlWriter.writeElementString("trans_no", trans_no);
                    xmlWriter.writeEndElement();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未产生批次交易文件";
            }

            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            String base64Str = Base64Encode(xmlWriter.toXmlString());
            String data_content = encryptByPriPfxFile(base64Str, actItem.ownKeyStorePath, actItem.ownKeyPassword);

            postParams.put("data_content", data_content);
            postParams.put("version", "4.0.0");

            // 请求报文
            WriteBankLogLn("加密数据: " + xmlWriter.toXmlString());

            String[] tmpStrRet = sendToBank("withdrawQuery", postParams, actItem);


            if (tmpStrRet[0].length() == 0) {
                String decryptStr = decryptByPubCerFile(tmpStrRet[1], actItem.oppCertFilePath);
                //第二步BASE64解密
                String respXml = Base64Decode(decryptStr);

                WriteBankLogStep3(respXml);

                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(respXml, tmpSbMsg);

                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/trans_content/trans_head/return_code");
                    String tmpRetMsg = tmpBkReader.getFirstText("/trans_content/trans_head/return_msg");

                    if (tmpRetCode.equals("0000")) {
                        retAts.respCode = "0";
                        retAts.respInfo = tmpRetMsg;
                        retAts.reqSeqID = p_req1998.reqBatchNO;
                        retAts.transState = "";
                        retAts.payInfoCode = tmpRetCode;
                        retAts.writeBeforeDetail();

                        while (tmpBkReader.read("/trans_content/trans_reqDatas/trans_reqData")) {
                            RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                            tmpRetDetail.recAct = tmpBkReader.readedXElement.getSingleText("to_acc_no");
                            tmpRetDetail.recName = tmpBkReader.readedXElement.getSingleText("to_acc_name");
                            tmpRetDetail.payAmount = tmpBkReader.readedXElement.getSingleText("trans_money");
                            tmpRetDetail.usage = tmpBkReader.readedXElement.getSingleText("trans_summary");
                            tmpRetDetail.result = tmpRetCode + "＋" + tmpBkReader.readedXElement.getSingleText("state");
                            tmpRetDetail.payInfoCode = tmpRetDetail.result;

                            retAts.writeRetDetail(tmpRetDetail);
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpRetMsg;
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.getMessage();
            e.printStackTrace();
        } finally {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
            if (fis != null) {
                fis.close();
            }
        }

        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1998.reqBatchNO;
        }

        if (retAts.respCode.equals("-1")) {
            retAts.writeBeforeDetail();
        }

        retAts.writeAfterDetail();
        return retAts;
    }

    /**
     * 宝付批量代扣
     */
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req9188.reqHeader);

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req9188.ownAct, "");
            if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath) || !FileHelper.existFile(actItem.oppCertFilePath)) {
                retAts.respCode = "0";
                if (actItem == null) {
                    retAts.respInfo = "未找到账号" + p_req9188.ownAct + "的批量商户配置节点";
                } else {
                    retAts.respInfo = "账号" + p_req9188.ownAct + "的证书文件不存在";
                }
                retAts.reqSeqID = p_req9188.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }

            Map<String, String> postParams = new HashMap<String, String>();

            postParams.put("version", "4.0.0.0");
            postParams.put("terminal_id", actItem.termId);
            postParams.put("member_id", actItem.merchantId);
            postParams.put("txn_type", "0631");
            postParams.put("txn_sub_type", "18");
            postParams.put("data_type", "xml");
//	        postParams.put("data_content", "");

            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\" ?>");
            xmlWriter.writeStartElement("data_content");
            xmlWriter.writeElementString("terminal_id", actItem.termId);
            xmlWriter.writeElementString("member_id", actItem.merchantId);
            xmlWriter.writeElementString("txn_sub_type", "18");
            xmlWriter.writeElementString("trans_serial_no", p_req9188.reqHeader.reqSeqID);
            xmlWriter.writeElementString("trans_batch_id", p_req9188.reqBatchNO);
            xmlWriter.writeStartElement("actual_info");

            while (p_req9188.readRecord()) {
                String trans_id = p_req9188.readedDetail.askNumber;
                String trans_date = Format.DateTime14Format.format(new Date());
                String acc_no = p_req9188.readedDetail.payAct;
                String id_holder = p_req9188.readedDetail.payName;
                String id_card_type = "01";
                String id_card = p_req9188.readedDetail.certNum;
                String mobile = p_req9188.readedDetail.cellPhone;
                String txn_amt = StringHelper.amountMultiply100(p_req9188.readedDetail.payAmount);
                String req_reserved = "保留域";

                // 单笔详细信息
                String singleDetail = trans_id + "#" + trans_date + "#" + acc_no + "#" + id_holder + "#" + id_card_type + "#" + id_card + "#" + mobile + "#" + txn_amt + "#" + req_reserved;

                xmlWriter.writeElementString("info", singleDetail);
            }

            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            String base64Str = Base64Encode(xmlWriter.toXmlString());
            String data_content = encryptByPriPfxFile(base64Str, actItem.ownKeyStorePath, actItem.ownKeyPassword);

            postParams.put("data_content", data_content);

            // 请求报文
            WriteBankLogLn("加密数据: " + xmlWriter.toXmlString());

            String[] tmpStrRet = sendToBank("withhold", postParams, actItem);

            //解析银行返回
            if (tmpStrRet[0].length() == 0) {
                if (tmpStrRet[1].contains("trans_content")) {
                    //明文返回,报文错误处理
                    retAts.respCode = "-1";
                    retAts.respInfo = "报文参数设置错误";
                } else {
                    //密文返回
                    //第一步：公钥解密
                    String decryptStr = decryptByPubCerFile(tmpStrRet[1], actItem.oppCertFilePath);
                    //第二步BASE64解密
                    String respXml = Base64Decode(decryptStr);

                    WriteBankLogStep3(respXml);

                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(respXml, tmpSbMsg);

                    if (tmpBkReader != null) {
                        String tmpRespCode = tmpBkReader.getFirstText("/result/resp_code");

                        if (tmpRespCode.equals("0000")) {
                            retAts.respCode = "0";
                            retAts.respInfo = tmpBkReader.getFirstText("/result/resp_msg");
                            retAts.reqSeqID = tmpBkReader.getFirstText("/result/batch_id");
                            retAts.transState = tmpBkReader.getFirstText("/result/resp_code");
                            ;
                            retAts.payInfoCode = retAts.transState;
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = tmpBkReader.getFirstText("/result/resp_msg");
                            retAts.transState = PaymentState.FAIL_Batch;
                            retAts.payInfoCode = tmpRespCode;
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpSbMsg.toString();
                    }
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL) || tmpStrRet[0].equals(FailCode.E9981)) {
                retAts.respCode = "0";
                retAts.respInfo = tmpStrRet[1];
                retAts.reqSeqID = p_req9188.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = tmpStrRet[1];
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            e.printStackTrace();
        }

        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req9188.reqBatchNO;
        }
        retAts.writeRetToATS();
        return retAts;
    }

    /**
     * 宝付批量代扣状态查询
     */
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req9198.reqHeader);
        retAts.respCode = "";

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req9198.ownAct, "");
            if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath) || !FileHelper.existFile(actItem.oppCertFilePath)) {
                retAts.respCode = "0";
                if (actItem == null) {
                    retAts.respInfo = "未找到账号" + p_req9198.ownAct + "的批量商户配置节点";
                } else {
                    retAts.respInfo = "账号" + p_req9198.ownAct + "的证书文件不存在";
                }
                retAts.reqSeqID = p_req9198.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                return retAts;
            }

            Map<String, String> postParams = new HashMap<String, String>();

            postParams.put("version", "4.0.0.0");
            postParams.put("terminal_id", actItem.termId);
            postParams.put("txn_type", "0631");
            postParams.put("txn_sub_type", "19");
            postParams.put("member_id", actItem.merchantId);
            postParams.put("data_type", "xml");
//	        postParams.put("data_content", "");

            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\" ?>");
            xmlWriter.writeStartElement("data_content");
            xmlWriter.writeElementString("txn_sub_type", "19");
            xmlWriter.writeElementString("terminal_id", actItem.termId);
            xmlWriter.writeElementString("member_id", actItem.merchantId);
            xmlWriter.writeElementString("trans_serial_no", "TISN" + System.currentTimeMillis());
            xmlWriter.writeElementString("batch_id", "");
            if (!p_req9198.reqBatchNO.equals("")) {
                xmlWriter.writeElementString("trans_batch_id", p_req9198.reqBatchNO);
            }

            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            String base64Str = Base64Encode(xmlWriter.toXmlString());
            String data_content = encryptByPriPfxFile(base64Str, actItem.ownKeyStorePath, actItem.ownKeyPassword);

            postParams.put("data_content", data_content);

            // 请求报文
            WriteBankLogLn("加密数据: " + xmlWriter.toXmlString());

            String[] tmpStrRet = sendToBank("withhold", postParams, actItem);

            // 解析银行返回
            if (tmpStrRet[0].length() == 0) {
                if (tmpStrRet[1].contains("trans_content")) {
                    //明文返回,报文错误处理
                    retAts.respCode = "-1";
                    retAts.respInfo = "报文参数设置错误";
                } else {
                    //密文返回
                    //第一步：公钥解密
                    String decryptStr = decryptByPubCerFile(tmpStrRet[1], actItem.oppCertFilePath);
                    //第二步BASE64解密
                    String respXml = Base64Decode(decryptStr);

                    WriteBankLogStep3(respXml);

                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(respXml, tmpSbMsg);

                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/result/resp_code");
                        String tmpRetMsg = tmpBkReader.getFirstText("/result/resp_msg");

                        if (tmpRetCode.equals("0000")) {
                            retAts.respCode = "0";
                            retAts.respInfo = tmpRetMsg;
                            retAts.reqSeqID = p_req9198.reqBatchNO;
                            retAts.transState = "";
                            retAts.payInfoCode = tmpRetCode;
                            retAts.writeBeforeDetail();

                            while (tmpBkReader.read("/result/actual_info")) {
                                RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                                String singleRespDetail = tmpBkReader.readedXElement.getSingleText("info");
                                String retStr[] = singleRespDetail.split("#");

                                tmpRetDetail.result = retStr[2] + "+" + retStr[1];
                                tmpRetDetail.payInfoCode = retStr[2];
                                tmpRetDetail.payAmount = retStr[5];
                                tmpRetDetail.postScript = retStr[0];

                                retAts.writeRetDetail(tmpRetDetail);
                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = tmpRetMsg;
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpSbMsg.toString();
                    }
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.getMessage();
            e.printStackTrace();
        }

        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req9198.reqBatchNO;
        }

        if (retAts.respCode.equals("-1")) {
            retAts.writeBeforeDetail();
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}
